import router from '@/router';
import store from '@/store';
import axios from 'axios'
import { Message } from 'element-ui'
import qs from 'qs';

const request = axios.create({
  // 配置选项
  // baseUrl
  // timeout
})

function redirectLogin() {
  router.push({
    name: 'login',
    query: {
      redirect: router.currentRoute.fullPath
    }
  })
}

function refreshToken() {
  return axios.create()({
    method: 'POST',
    url: '/front/user/refresh_token',
    data: qs.stringify({
      refreshtoken: store.state.user.refresh_token
    })
  })
}

// 请求拦截器
request.interceptors.request.use(function (config) {
  const { user } = store.state
  if (user?.access_token) {
    config.headers.Authorization = user.access_token
  }
  return config;
}, function (error) {
  // Do something with request error
  return Promise.reject(error);
});

let isRefreshing = false // 控制刷新 token 
let requests: Function[] = [] // 存储刷新 token 错误的请求
// 响应拦截器
request.interceptors.response.use(function (response) { // 当状态码为2xx都会进入这里
  return response;
}, async function (error) {
  if (error.response) { // 请求收到相应了，但是状态码超出了 2xx 范围
    const { status } = error.response
    if (status === 400) {
      Message.error('请求参数错误')
    } else if (status === 401) {
      // token 无效(未登录，过期)
      if (!store.state.user) {
        redirectLogin()
        return Promise.reject(error)
      }

      // 尝试刷新获取新的 token
      if (!isRefreshing) {
        isRefreshing = true // 开启刷新状态
        return refreshToken()
          .then(res => {
            if (!res.data.success) {
              throw new Error('刷新 Token 失败')
            }
            // 刷新 token 成功了
            store.commit('setUser', res.data.content)
            // 把 requests 队列中的请求重新发出去
            requests.forEach(cb => cb())
            // 重置requests数组
            requests = []
            // 重新发送失败的请求
            // console.log(error.config) // 失败请求的请求配置信息
            return request(error.config)
          })
          .catch(err => {
            console.log(err)
            store.commit('setUser', null)
            redirectLogin()
            return Promise.reject(error)
          })
      }

      // 刷新状态下，吧请求挂起放到requests数组中
      return new Promise(resolve => {
        requests.push(() => {
          resolve(request(error.config))
        })
      })


    } else if (status === 403) {
      Message.error('没有权限，请联系管理员')
    } else if (status === 404) {
      Message.error('请求资源不存在')
    } else if (status >= 500) {
      Message.error('服务端错误，请联系管理员')
    }
  } else if (error.request) { // 请求发出去没有收到相应
    Message.error('请求超时，请刷新重试')
  } else { // 在设置请求是发生了一些事情，触发了一个错误
    Message.error(`请求失败，${error.message}`)
  }
  // 把请求失败的错误对象继续抛出，扔给下一个调用者
  return Promise.reject(error);
});

export default request